import argparse
from pathlib import Path
from pydantic import BaseModel
from .delly import DELLY
from .anno import Annotation
from .image import Image


class MTDD(BaseModel):
    sample: str
    shifted_bam_file: Path
    nonshift_bam_file: Path
    shift_back_chain_file: Path
    nonshift_reference_file: Path
    shifted_reference_file: Path
    outdir: Path
    min_size: int
    max_size: int
    supported_reads: int
    genepred_file: Path
    gene_file: Path

    @property
    def depth_file(self) -> Path:
        return self.outdir / f"{self.sample}.depth.tsv"

    @property
    def delly_vcf_file(self) -> Path:
        return self.outdir / f"{self.sample}.delly.vcf"

    @property
    def vcf_file(self) -> Path:
        return self.outdir / f"{self.sample}.mt.vcf"

    @property
    def image_file(self) -> Path:
        return self.outdir / f"{self.sample}.mt.circos.png"

    def do_delly(self):
        if not self.delly_vcf_file.exists() or not self.depth_file.exists():
            delly_nonshift = DELLY(
                out_prefix=self.outdir / f"{self.sample}.nonshift",
                bam_file=self.nonshift_bam_file,
                reference_file=self.nonshift_reference_file,
                max_size=self.max_size,
                min_size=self.min_size,
                supported_reads=self.supported_reads,
            )
            delly_shifted = DELLY(
                out_prefix=self.outdir / f"{self.sample}.shifted",
                bam_file=self.shifted_bam_file,
                reference_file=self.shifted_reference_file,
                shift_back_chain_file=self.shift_back_chain_file,
                max_size=self.max_size,
                min_size=self.min_size,
                supported_reads=self.supported_reads,
            )
            if not self.delly_vcf_file.exists():
                delly_nonshift.do_delly()
                delly_shifted.do_delly()
                DELLY.merge_vcf_files([delly_nonshift.vcf_file, delly_shifted.vcf_file], self.delly_vcf_file)

            if not self.depth_file.exists():
                delly_nonshift.do_depth()
                delly_shifted.do_depth()
                DELLY.merge_depth_files([delly_nonshift.depth_file, delly_shifted.depth_file], self.depth_file)

    def do_annotation(self):
        if not self.vcf_file.exists():
            Annotation(
                in_vcf_file=self.delly_vcf_file,
                out_vcf_file=self.vcf_file,
                genepred_file=self.genepred_file,
                gene_file=self.gene_file,
            ).run()

    def do_image(self):
        if not self.image_file.exists():
            Image(
                depth_file=self.depth_file,
                genepred_file=self.genepred_file,
                vcf_file=self.vcf_file,
                image_file=self.image_file,
            ).run()

    def run(self):
        self.do_delly()
        self.do_annotation()
        self.do_image()


def main():
    parser = argparse.ArgumentParser(description="Mitochondria Detect Deletion(MTDD)")
    parser.add_argument("--sample", "-s", required=True, help="sample name")
    parser.add_argument("--nonshift_bam_file", "-bam1", type=Path, required=True, help="input, Nonshift BAM file")
    parser.add_argument("--shifted_bam_file", "-bam2", type=Path, required=True, help="input, Shifted BAM file")
    parser.add_argument("--nonshift_reference_file", "-ref1", type=Path, required=True, help="input, Nonshift Reference file")
    parser.add_argument("--shifted_reference_file", "-ref2", type=Path, required=True, help="input, Shifted Reference file")
    parser.add_argument("--shift_back_chain_file", "-chain", type=Path, required=True, help="input, ShiftBack chain file of liftover")
    parser.add_argument("--genepred_file", "-gpe", type=Path, required=True, help="input, Gene Pred file")
    parser.add_argument("--gene_file", "-gene", type=Path, required=True, help="input, GeneID file")
    parser.add_argument("--min_size", "-min", default=500, type=int, help="parameter, min CNV size")
    parser.add_argument("--max_size", "-max", default=10000, type=int, help="parameter, max CNV size")
    parser.add_argument("--supported_reads", "-reads", default=25, type=int, help="parameter, min supported reads")
    parser.add_argument("--outdir", "-o", default=".", type=Path, help="output, output directory")
    parser.set_defaults(func=lambda args: MTDD(**vars(args)).run())
    args = parser.parse_args()
    args.func(args)
